<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>7. 小程序自定义组件 | 被删的前端游乐场</title>
    <meta name="description" content="Just playing around">
    
    
    <link rel="preload" href="/front-end-playground/assets/css/0.styles.a683ed26.css" as="style"><link rel="preload" href="/front-end-playground/assets/js/app.e5cf4092.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/3.c853767c.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/2.eed49fdd.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/126.0cd02de4.js" as="script">
    <link rel="stylesheet" href="/front-end-playground/assets/css/0.styles.a683ed26.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/front-end-playground/" class="home-link router-link-active"><!----> <span class="site-name">被删的前端游乐场</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link">前端基础</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link router-link-active">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link">前端基础</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link router-link-active">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0" style="padding-top:10px;"><div class="kitty-main" data-v-0cd75e06><span class="stand" data-v-0cd75e06></span> <div class="cat" data-v-0cd75e06><div class="body" data-v-0cd75e06></div> <div class="head" data-v-0cd75e06><div class="ear" data-v-0cd75e06></div> <div class="ear" data-v-0cd75e06></div></div> <div class="face" data-v-0cd75e06><div class="nose" data-v-0cd75e06></div> <div class="whisker-container" data-v-0cd75e06><div class="whisker" data-v-0cd75e06></div> <div class="whisker" data-v-0cd75e06></div></div> <div class="whisker-container" data-v-0cd75e06><div class="whisker" data-v-0cd75e06></div> <div class="whisker" data-v-0cd75e06></div></div></div> <div class="tail-container" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06><div class="tail" data-v-0cd75e06></div></div></div></div></div></div></div></div></div></div> <p class="sidebar-heading open"><span>小程序原理</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/front-end-playground/wxapp/wxapp-principle/1-wxapp-generate.html" class="sidebar-link">1. 小程序的诞生</a></li><li><a href="/front-end-playground/wxapp/wxapp-principle/2-wxapp-technology-architecture.html" class="sidebar-link">2. 小程序的底层框架</a></li><li><a href="/front-end-playground/wxapp/wxapp-principle/3-wxapp-set-data.html" class="sidebar-link">3. 解剖小程序的setData</a></li><li><a href="/front-end-playground/wxapp/wxapp-principle/4-wxapp-manage-and-security.html" class="sidebar-link">4. 理解小程序的安全与管控</a></li><li><a href="/front-end-playground/wxapp/wxapp-principle/5-wxapp-basic-lib.html" class="sidebar-link">5. 关于小程序的基础库</a></li><li><a href="/front-end-playground/wxapp/wxapp-principle/6-wxapp-page-and-navigate.html" class="sidebar-link">6. 小程序页面管理与跳转</a></li><li><a href="/front-end-playground/wxapp/wxapp-principle/7-wxapp-component.html" class="active sidebar-link">7. 小程序自定义组件</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front-end-playground/wxapp/wxapp-principle/7-wxapp-component.html#why" class="sidebar-link">why</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/wxapp/wxapp-principle/7-wxapp-component.html#一切都从-virtual-dom-说起" class="sidebar-link">一切都从 Virtual DOM 说起</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/wxapp/wxapp-principle/7-wxapp-component.html#shadow-dom-模型" class="sidebar-link">Shadow DOM 模型</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/wxapp/wxapp-principle/7-wxapp-component.html#shadow-tree-拼接" class="sidebar-link">Shadow Tree 拼接</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/wxapp/wxapp-principle/7-wxapp-component.html#双线程的难题" class="sidebar-link">双线程的难题</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/wxapp/wxapp-principle/7-wxapp-component.html#page-和-component" class="sidebar-link">Page 和 Component</a></li></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0" style="padding-top:;"><!----> <p class="sidebar-heading"><span>小程序开发技巧</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0" style="padding-top:;"><!----> <p class="sidebar-heading"><span>小程序开发月刊</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p>小程序里，自定义组件作为一个贯穿小程序架构核心的组成，你对它又掌握了多少呢？</p> <h1 id="自定义组件"><a href="#自定义组件" aria-hidden="true" class="header-anchor">#</a> 自定义组件</h1> <h2 id="why"><a href="#why" aria-hidden="true" class="header-anchor">#</a> why</h2> <h3 id="代码的复用"><a href="#代码的复用" aria-hidden="true" class="header-anchor">#</a> 代码的复用</h3> <p>在起初小程序只支持 Page 的时候，就会有这样蛋疼的问题：多个页面有相同的组件，每个页面都要复制粘贴一遍，每次改动都要全局搜索一遍，还说不准哪里改漏了就出翔了。</p> <h3 id="组件化设计"><a href="#组件化设计" aria-hidden="true" class="header-anchor">#</a> 组件化设计</h3> <p>在前端项目中，组件化是很常见的方式，某块通用能力的抽象和设计，是一个必备的技能。组件的管理、数据的管理、应用状态的管理，这些在我们设计的过程中都是需要去思考的。当然你也可以说我就堆代码就好了，不过一个真正的码农是不允许自己这么随便的！</p> <p>所以，组件化是现代前端必须掌握的生存技能！</p> <h1 id="自定义组件的实现"><a href="#自定义组件的实现" aria-hidden="true" class="header-anchor">#</a> 自定义组件的实现</h1> <h2 id="一切都从-virtual-dom-说起"><a href="#一切都从-virtual-dom-说起" aria-hidden="true" class="header-anchor">#</a> 一切都从 Virtual DOM 说起</h2> <p>前面<a href="/front-end-playground/wxapp/wxapp-principle/3-wxapp-set-data.html">解剖小程序的 setData</a>有讲过，基于小程序的双线程设计，视图层（Webview 线程）和逻辑层（JS 线程）之间通信（表现为 setData），是基于虚拟 DOM 来实现数据通信和模版更新的。</p> <p>自定义组件一样的双线程，所以一样滴基于 Virtual DOM 来实现通信。那在这里，Virtual DOM 的一些基本知识（包括生成 VD 对象、Diff 更新等），就不过多介绍啦~</p> <h2 id="shadow-dom-模型"><a href="#shadow-dom-模型" aria-hidden="true" class="header-anchor">#</a> Shadow DOM 模型</h2> <p>基于 Virtual DOM，我们知道在这样的设计里，需要一个框架来支撑维护整个页面的节点树相关信息，包括节点的属性、事件绑定等。在小程序里，Exparser 承担了这个角色。</p> <p>前面 <a href="./5-wxapp-basic-lib">5.关于小程序的基础库</a> 也讲过，Exparser 的主要特点包括：</p> <ul><li>基于 Shadow DOM 模型</li> <li>可在纯 JS 环境中运行</li></ul> <p>Shadow DOM 是什么呢，它就是我们在写代码时候写的自定义组件、内置组件、原生组件等。Shadow DOM 为 Web 组件中的 DOM 和 CSS 提供了封装。Shadow DOM 使得这些东西与主文档的 DOM 保持分离。</p> <p>简而言之，Shadow DOM 是一个 HTML 的新规范，其允许开发者封装 HTML 组件（类似 vue 组件，将 html，css，js 独立部分提取）。</p> <p>例如我们定义了一个自定义组件叫<code>&lt;my-component&gt;</code>，你在开发者工具可以见到：
<img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/wxapp-component-1.jpg" alt="Shadow DOM"></p> <p><code>#shadow-root</code>称为影子根，DOM 子树的根节点，和文档的主要 DOM 树分开渲染。可以看到它在<code>&lt;my-component&gt;</code>里面，换句话说，<code>#shadow-root</code>寄生在<code>&lt;my-component&gt;</code>上。<code>#shadow-root</code>可以嵌套，形成节点树，即称为影子树（Shadow Tree）。</p> <p>像这样：
<img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/wxapp-component-2.jpg" alt="Shadow Tree"></p> <h2 id="shadow-tree-拼接"><a href="#shadow-tree-拼接" aria-hidden="true" class="header-anchor">#</a> Shadow Tree 拼接</h2> <p>既然组件是基于 Shadow DOM，那组件的嵌套关系，其实也就是 Shadow DOM 的嵌套，也可称为 Shadow Tree 的拼接。</p> <p>Shadow Tree 拼接是怎么做的呢？一切又得从模版引擎讲起。</p> <p>我们知道，Virtual DOM 机制会将节点解析成一个对象，那这个对象要怎么生成真正的 DOM 节点呢？数据变更又是怎么更新到界面的呢？这大概就是模版引擎做的事情了。</p> <p><a href="/front-end-playground/front-end-basic/understanding/template-engine.html">《前端模板引擎》</a>里有详细描述模版引擎的机制，通常来说主要有这些：</p> <ul><li>DOM 节点的创建和管理：<code>appendChild</code>/<code>insertBefore</code>/<code>removeChild</code>/<code>replaceChild</code>等</li> <li>DOM 节点的关系（嵌套的处理）：<code>parentNode</code>/<code>childNodes</code></li> <li>通常创建后的 DOM 节点会保存一个映射，在更新的时候取到映射，然后进行处理（通常包括替换节点、改变内容<code>innerHTML</code>、移动删除新增节点、修改节点属性<code>setAttribute</code>）</li></ul> <p>在上面的图我们也可以看到，在 Shadow Tree 拼接的过程中，有些节点并不会最终生成 DOM 节点，例如<code>&lt;slot&gt;</code>这种。</p> <p>但是，常用的前端模版引擎，能直接用在小程序里吗？</p> <h2 id="双线程的难题"><a href="#双线程的难题" aria-hidden="true" class="header-anchor">#</a> 双线程的难题</h2> <h3 id="自定义组件渲染流程"><a href="#自定义组件渲染流程" aria-hidden="true" class="header-anchor">#</a> 自定义组件渲染流程</h3> <p>双线程的设计，给小程序带来了很多便利，安全性管控力都拥有了，当然什么鬼东西都可以比作一把双刃剑，双线程也不例外。</p> <p>我们知道，小程序分为 Webview 和 JS 双线程，逻辑层里是没法拿到真正的 DOM 节点，也没法随便动态变更页面的。那在这种情况下，我们要怎么去使用映射来更新模版呢（因为我们压根拿不到 Webview 节点的映射）？</p> <p>所以在双线程下，其实两个线程都需要保存一份节点信息。这份节点信息怎么来的呢？其实就是我们需要在创建组件的时候，通过事件通知的方式，分别在逻辑层和视图层创建一份节点信息。</p> <p>同时，视图层里的组件是有层级关系的，但是 JS 里没有怎么办？为了维护好父子嵌套等节点关系，所以我们在 逻辑层也需要维护一棵 Shadow Tree。</p> <p>那么我们自定义组件的渲染流程大概是：</p> <ol><li>组件创建。</li></ol> <ul><li>逻辑层：先是 wxml + js 生成一个 JS 对象（因为需要访问组件实例 this 呀），然后是 JS 其中节点部分生成 Virtual DOM，拼接 Shadow Tree 什么的，最后通过底层通信通知到 视图层</li> <li>视图层：拿到节点信息，然后吭哧吭哧开始创建 Shadow DOM，拼接 Shadow Tree 什么的,最后生成真实 DOM，并保留下映射关系</li></ul> <ol start="2"><li>组件更新。</li></ol> <p>这时候我们知道，不管是逻辑层，还是视图层，都维护了一份 Shadow Tree，要怎么保证他们之间保持一致呢？</p> <h3 id="让-js-和-webview-的组件保持一致"><a href="#让-js-和-webview-的组件保持一致" aria-hidden="true" class="header-anchor">#</a> 让 JS 和 Webview 的组件保持一致</h3> <p>为了让两边的 Shadow Tree 保持一致，可以使用同步队列来传递信息。（这样就不会漏掉啦）</p> <p>同步队列可以，每次变动我们就往队列里塞东西就好了。不过这样还会有个问题，我们也知道 setData 其实在实际项目里是使用比较频繁的，要是像 Component 的 observer 里做了 setData 这类型的操作，那不是每次变动会导致一大堆的 setDate？这样通信效率会很低吧？</p> <p>所以，其实可以把一次操作里的所有 setData 都整到一次通信里，通过排序保证好顺序就好啦。</p> <h2 id="page-和-component"><a href="#page-和-component" aria-hidden="true" class="header-anchor">#</a> Page 和 Component</h2> <h3 id="component-是-page-的超集"><a href="#component-是-page-的超集" aria-hidden="true" class="header-anchor">#</a> Component 是 Page 的超集</h3> <p>事实上，小程序的页面也可以视为自定义组件。因而，页面也可以使用<code>Component</code>构造器构造，拥有与普通组件一样的定义段与实例方法。但此时要求对应 json 文件中包含<code>usingComponents</code>定义段。</p> <blockquote><p>来自<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/component.html" target="_blank" rel="noopener noreferrer">官方文档-Component<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p></blockquote> <p>所以，基于 Component 是 Page 的超集，那么其实组件的渲染流程、方式，其实跟页面没多大区别，应该可以一个方式去理解就差不多啦。</p> <h3 id="页面渲染"><a href="#页面渲染" aria-hidden="true" class="header-anchor">#</a> 页面渲染</h3> <p>既然页面就是组件，那其实页面的渲染流程跟组件的渲染流程基本保持一致。</p> <p>视图层渲染，可以参考<a href="https://developers.weixin.qq.com/ebook?action=get_post_info&amp;token=935589521&amp;volumn=1&amp;lang=zh_CN&amp;book=miniprogram&amp;docid=00024a319d00b87b008612f5f5640a" target="_blank" rel="noopener noreferrer">7.4 视图层渲染<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>说明。</p> <h1 id="结束语"><a href="#结束语" aria-hidden="true" class="header-anchor">#</a> 结束语</h1> <p>其实很多新框架新工具出来的时候，经常会让人眼前一亮，觉得哇好厉害，哇好高大上。<br>
但其实更多时候，我们需要挖掘新事物的核心，其实大多数都是在原有的事物上增加了个新视角，从不一样的视角看，看到的就不一样了呢。作为一名码农，我们要看到不变的共性，变化的趋势。</p></div> <!----> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/godbasin/front-end-playground/edit/sourcecode/docs/wxapp/wxapp-principle/7-wxapp-component.md" target="_blank" rel="noopener noreferrer">帮阿猪改善此页面！</a> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div> <!----> <blockquote>部分文章中使用了一些网站的截图，如果涉及侵权，请告诉我删一下谢谢~</blockquote> <div style="margin-top:30px;"><div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-sm-0 el-col-md-2 el-col-lg-4" style="padding-left:10px;padding-right:10px;display:block;"><div style="width:1px;height:1px;"></div></div> <div class="el-col el-col-24 el-col-sm-24 el-col-md-18 el-col-lg-16" style="padding-left:10px;padding-right:10px;"><div class="el-card box-card is-always-shadow"><div class="el-card__header"><div class="clearfix"><span>温馨提示喵</span></div></div><div class="el-card__body"> <div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="el-image"><div class="image-slot"><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/loading.gif" style="width:100%;"></div><!----></div></div> <div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="copyright-text"><div>本文版权归作者所有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。</div> <div>出处：被删的前端游乐场</div> <div>作者：<a href="https://github.com/godbasin" target="_blank">被删</a></div></div></div></div></div></div></div></div></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/front-end-playground/wxapp/wxapp-principle/6-wxapp-page-and-navigate.html" class="prev">
          6. 小程序页面管理与跳转
        </a></span> <span class="next"><a href="/front-end-playground/wxapp/wxapp-technique/wxapp-official-functions.html">
          超实用小程序官方能力
        </a>
        →
      </span></p></div>  <div class="gitalk-container theme-default-content"><div id="gitalk-container" class="content"></div></div></main> <div id="kitty-container"><span><div role="tooltip" id="el-popover-1065" aria-hidden="true" class="el-popover el-popper" style="width:undefinedpx;display:none;"><!----><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/2code2.jpg" class="image"> <div class="text">牡羊猪的猫粮罐</div> </div><div id="kitty" style="background:url(https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/kitty1.svg);"></div></span> <div class="el-dialog__wrapper" style="display:none;"><div role="dialog" aria-modal="true" aria-label="牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）" class="el-dialog" style="margin-top:15vh;"><div class="el-dialog__header"><span class="el-dialog__title">牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）</span><button type="button" aria-label="Close" class="el-dialog__headerbtn"><i class="el-dialog__close el-icon el-icon-close"></i></button></div><!----><!----></div></div></div></div><div class="global-ui"></div></div>
    <script src="/front-end-playground/assets/js/app.e5cf4092.js" defer></script><script src="/front-end-playground/assets/js/3.c853767c.js" defer></script><script src="/front-end-playground/assets/js/2.eed49fdd.js" defer></script><script src="/front-end-playground/assets/js/126.0cd02de4.js" defer></script>
  </body>
</html>
